package com.robotic.sensor.service;

import com.robotic.sensor.domain.SensorData;
import com.robotic.sensor.service.CoordinateRegionService;
import com.robotic.sensor.service.ISensorDataService;
import com.robotic.sensor.service.TemperatureSensorService;
import com.robotic.tcp.RobotMonitor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
 * 机器人坐标监控服务
 * 定时检查机器人当前坐标是否在标准区域内，并执行相应的传感器数据检测
 *
 * @author robotic
 * @date 2024-01-20
 */
@Slf4j
@Service
public class RobotCoordinateMonitorService {

    @Autowired
    private CoordinateRegionService coordinateRegionService;

    @Autowired
    private ISensorDataService sensorDataService;

    @Autowired
    private TemperatureSensorService temperatureSensorService;

    // 定时任务执行器
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);

    // 存储每个机器人的监控任务
    private final ConcurrentHashMap<String, ScheduledFuture<?>> monitorTasks = new ConcurrentHashMap<>();

    // 检查间隔（秒）
    private static final int CHECK_INTERVAL_SECONDS = 5;

    /**
     * 启动机器人坐标监控
     *
     * @param robotId 机器人ID
     * @param taskId 任务ID
     */
    public void startMonitoring(Long robotId, Long taskId) {
        String key = generateKey(robotId, taskId);

        // 如果已经在监控中，先停止
        stopMonitoring(robotId, taskId);

        log.info("启动机器人坐标监控: robotId={}, taskId={}", robotId, taskId);

        ScheduledFuture<?> task = scheduler.scheduleAtFixedRate(
            () -> checkRobotCoordinateAndSensorData(robotId, taskId),
            0, // 立即开始
            CHECK_INTERVAL_SECONDS,
            TimeUnit.SECONDS
        );

        monitorTasks.put(key, task);
    }

    /**
     * 停止机器人坐标监控
     *
     * @param robotId 机器人ID
     * @param taskId 任务ID
     */
    public void stopMonitoring(Long robotId, Long taskId) {
        String key = generateKey(robotId, taskId);
        ScheduledFuture<?> task = monitorTasks.remove(key);

        if (task != null && !task.isCancelled()) {
            task.cancel(false);
            log.info("停止机器人坐标监控: robotId={}, taskId={}", robotId, taskId);
        }
    }

    /**
     * 停止所有监控任务
     */
    public void stopAllMonitoring() {
        log.info("停止所有机器人坐标监控任务");
        monitorTasks.values().forEach(task -> {
            if (!task.isCancelled()) {
                task.cancel(false);
            }
        });
        monitorTasks.clear();
    }

    /**
     * 检查机器人坐标并执行传感器数据检测
     *
     * @param robotId 机器人ID
     * @param taskId 任务ID
     */
    private void checkRobotCoordinateAndSensorData(Long robotId, Long taskId) {
        try {
            // 获取机器人当前坐标
            Double currentX = getCurrentRobotX();
            Double currentY = getCurrentRobotY();
            Double currentZ = getCurrentRobotZ();

            if (currentX == null || currentY == null) {
                log.debug("机器人坐标数据不可用: robotId={}, x={}, y={}, z={}", robotId, currentX, currentY, currentZ);
                return;
            }

            log.debug("检查机器人坐标: robotId={}, x={}, y={}, z={}", robotId, currentX, currentY, currentZ);

            // 根据坐标判断当前区域
            String regionCode = coordinateRegionService.getRegionByCoordinate(currentX, currentY, currentZ);

            if (regionCode != null) {
                log.debug("机器人当前位于区域: {}", regionCode);

                // 执行温度传感器数据检测
                performTemperatureSensorCheck(robotId, taskId, currentX, currentY, currentZ, regionCode);

                // 这里可以添加其他类型的传感器检测
                // performGasSensorCheck(robotId, taskId, currentX, currentY, currentZ, regionCode);

            } else {
                log.debug("机器人当前不在任何已定义的区域内: robotId={}, x={}, y={}, z={}", robotId, currentX, currentY, currentZ);
            }

        } catch (Exception e) {
            log.error("检查机器人坐标和传感器数据时发生异常: robotId={}, taskId={}, error={}", robotId, taskId, e.getMessage(), e);
        }
    }

    /**
     * 执行温度传感器数据检测
     *
     * @param robotId 机器人ID
     * @param taskId 任务ID
     * @param x X坐标
     * @param y Y坐标
     * @param z Z坐标
     * @param regionCode 区域代码
     */
    private void performTemperatureSensorCheck(Long robotId, Long taskId, Double x, Double y, Double z, String regionCode) {
        try {
            // 假设温度传感器设备ID为1（可以根据实际情况配置）
            int temperatureDeviceId = 1;

            // 读取温度传感器数据
            SensorData temperatureData = temperatureSensorService.readTemperatureData(
                temperatureDeviceId,
                robotId,
                taskId,
                BigDecimal.valueOf(x),
                BigDecimal.valueOf(y)
            );

            if (temperatureData != null) {
                // 设置区域代码和Z坐标
                temperatureData.setRegionCode(regionCode);
                temperatureData.setCoordinateZ(z != null ? BigDecimal.valueOf(z) : null);

                // 处理传感器数据（包含判断和保存）
                boolean processed = sensorDataService.processRealtimeSensorData(temperatureData);

                if (processed) {
                    log.debug("温度传感器数据处理成功: robotId={}, regionCode={}, value={}",
                        robotId, regionCode, temperatureData.getValue());
                } else {
                    log.warn("温度传感器数据处理失败: robotId={}, regionCode={}", robotId, regionCode);
                }
            } else {
                log.debug("未读取到温度传感器数据: robotId={}, regionCode={}", robotId, regionCode);
            }

        } catch (Exception e) {
            log.error("执行温度传感器检测时发生异常: robotId={}, regionCode={}, error={}", robotId, regionCode, e.getMessage(), e);
        }
    }

    /**
     * 获取机器人当前X坐标
     */
    private Double getCurrentRobotX() {
        try {
            List<Object> xyList = RobotMonitor.xyList;
            if (xyList != null && !xyList.isEmpty()) {
                Object lastData = xyList.get(xyList.size() - 1);
                if (lastData instanceof com.alibaba.fastjson2.JSONObject) {
                    com.alibaba.fastjson2.JSONObject jsonData = (com.alibaba.fastjson2.JSONObject) lastData;
                    return jsonData.getDouble("posX");
                }
            }
        } catch (Exception e) {
            log.debug("获取机器人X坐标失败: {}", e.getMessage());
        }
        return null;
    }

    /**
     * 获取机器人当前Y坐标
     */
    private Double getCurrentRobotY() {
        try {
            List<Object> xyList = RobotMonitor.xyList;
            if (xyList != null && !xyList.isEmpty()) {
                Object lastData = xyList.get(xyList.size() - 1);
                if (lastData instanceof com.alibaba.fastjson2.JSONObject) {
                    com.alibaba.fastjson2.JSONObject jsonData = (com.alibaba.fastjson2.JSONObject) lastData;
                    return jsonData.getDouble("posY");
                }
            }
        } catch (Exception e) {
            log.debug("获取机器人Y坐标失败: {}", e.getMessage());
        }
        return null;
    }

    /**
     * 获取机器人当前Z坐标
     */
    private Double getCurrentRobotZ() {
        try {
            List<Object> xyList = RobotMonitor.xyList;
            if (xyList != null && !xyList.isEmpty()) {
                Object lastData = xyList.get(xyList.size() - 1);
                if (lastData instanceof com.alibaba.fastjson2.JSONObject) {
                    com.alibaba.fastjson2.JSONObject jsonData = (com.alibaba.fastjson2.JSONObject) lastData;
                    return jsonData.getDouble("posZ");
                }
            }
        } catch (Exception e) {
            log.debug("获取机器人Z坐标失败: {}", e.getMessage());
        }
        return null;
    }

    /**
     * 生成监控任务的唯一键
     */
    private String generateKey(Long robotId, Long taskId) {
        return robotId + "_" + taskId;
    }

    /**
     * 获取当前监控任务数量
     */
    public int getActiveMonitoringCount() {
        return monitorTasks.size();
    }

    /**
     * 检查指定机器人是否正在监控中
     */
    public boolean isMonitoring(Long robotId, Long taskId) {
        String key = generateKey(robotId, taskId);
        ScheduledFuture<?> task = monitorTasks.get(key);
        return task != null && !task.isCancelled();
    }

    /**
     * 关闭服务时清理资源
     */
    public void shutdown() {
        log.info("关闭机器人坐标监控服务");
        stopAllMonitoring();
        scheduler.shutdown();
        try {
            if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) {
                scheduler.shutdownNow();
            }
        } catch (InterruptedException e) {
            scheduler.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }
}
